package com.inspur.edp.bef.bemanager.generatedbo;

import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.beenum.BECategory;
import com.inspur.edp.bef.bizentity.common.SysnDboUtils;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityErrorCodeEnum;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityException;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspAssociationKeyCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociationKey;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.entity.GspCommonElement;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.lcm.databaseobject.api.DatabaseObjectServiceForWebIde;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.databaseobject.api.entity.*;
import io.iec.edp.caf.databaseobject.api.service.IDatabaseObjectRtService;
import lombok.var;

import java.util.UUID;

import static com.inspur.edp.bef.bemanager.util.CheckInfoUtil.checkNull;

public class DboGenerater {
    private final String dboExceptionCode = "BeGenerateDbo";
    private final DatabaseObjectServiceForWebIde dtService = SpringBeanUtils.getBean(DatabaseObjectServiceForWebIde.class);
    private final MetadataProjectService projectService = SpringBeanUtils.getBean(MetadataProjectService.class);
    private static IDatabaseObjectRtService databaseObjectRtService = SpringBeanUtils.getBean(IDatabaseObjectRtService.class);
    //private readonly IDatabaseObjectRtService rtService = ServiceManager.GetService<IDatabaseObjectRtService>();
    private String projectPath;

    public DboGenerater(String metadataPath) {
        this.projectPath = projectService.getMetadataProjInfo(metadataPath).getProjectPath();
    }

    /**
     * 根据业务实体获取
     *
     * @param be
     */
    public final void GenerateDboFromBizEntity(GspBusinessEntity be, String path) {
        // 若为dbe类型，则不生成dbo
        if (be.getCategory() == BECategory.DependentBusinessEntity) {
            return;
        }

        //todo:[启用时间戳]方案成熟前，先隐藏
        //bool isUsingTimeStamp = be.IsUsingTimeStamp;
        boolean isUsingTimeStamp = false;
        java.util.ArrayList<GspBizEntityObject> bizObjects = be.getAllNodes();
        // ① 找到设计时dbo文件  ->  修改，设计时dbo文件
        //if (rtService.IsExistDatabaseObject(bizObject.RefObjectName)&&rtService.GetDatabaseObject(bizObject.RefObjectName)  is DatabaseObjectTable rtDbo)
        //{
        //	//	② 无设计时dbo文件，找到运行时dbo  ->  修改, 运行时dbo
        //	modifyDbo(bizObject, path,rtDbo,isUsingTimeStamp);
        //}
        //else
        //{
        //	③ 无设计时dbo文件，无运行时dbo ->  创建，仍使用原有的dboID
        //}
        // ④ 未记录dboID  ->  创建
        for (GspBizEntityObject bizObject : bizObjects) {
            if(bizObject.isVirtual())
                continue;
            String dboID = bizObject.getRefObjectName();
            if (!checkNull(dboID)) {
                dtService.isExistDatabaseObject(path, null, dboID);
                if(dtService.getDatabaseObjectById(path,dboID) instanceof DatabaseObjectView){
                    continue;
                }
                if (dtService.getDatabaseObjectById(path, dboID) instanceof DatabaseObjectTable) {
                    DatabaseObjectTable dtDbo = (DatabaseObjectTable) dtService.getDatabaseObjectById(path, dboID);
                    modifyDbo(bizObject, path, dtDbo, isUsingTimeStamp);
                } else {
                    createDbo(bizObject, path, isUsingTimeStamp);
                }
            } else {
                createDbo(bizObject, path, isUsingTimeStamp);
            }
        }

    }


    ///#region create
    private void createDbo(GspBizEntityObject bizObject, String path, boolean isUsingTimeStamp) {
        DatabaseObjectTable table = GenerateDboFromBizObject(bizObject, path, bizObject.getRefObjectName(), isUsingTimeStamp);
        bizObject.setRefObjectName(table.getId());
        dtService.saveDatabaseObjectTableWithoutFileName(path, table);
    }

    /**
     * 主对象获取当前be上设置的是否使用时间戳字段
     *
     * @param bizObject        当前对象
     * @param isUsingTimeStamp 是否生成时间戳字段
     * @return
     */
    private boolean GetIsUsingTimeStamp(GspBizEntityObject bizObject, boolean isUsingTimeStamp) {
        if (bizObject.getObjectType() == GspCommonObjectType.MainObject) {
            return isUsingTimeStamp;
        }
        return false;
    }

    /**
     * 根据业务实体对象创建dbo
     *
     * @param bizObject
     * @param path
     * @param dboID          有值，则对应已有dbo但是无法找到的情况，此时新建原有dboID的dbo; 若为空，则完全新建dbo
     * @param usingTimeStamp 是否生成时间戳字段
     * @return
     */
    private DatabaseObjectTable GenerateDboFromBizObject(GspBizEntityObject bizObject, String path, String dboID, boolean usingTimeStamp) {
        //20180802修改_由于外层已确认设计时/运行时均无此dbo，故仅使用原dboID新建
        String dboCode = GetDboNameWithAppCode(bizObject.getCode());
        String dboName = bizObject.getName();

        //20180817 dbo添加[是否生成时间戳][是否年度表]
        boolean isFiscalTable = false;
        boolean isUsingTimeStamp = GetIsUsingTimeStamp(bizObject, usingTimeStamp);

        //新建dbo时，检查dbo文件名/表名
        checkDboFileNameRepeat(path, dboCode);
        checkDboTableNameRepeat(path, dboCode, dboID);

        DatabaseObjectTable table = new DatabaseObjectTable(dboCode, dboName, false, false, isUsingTimeStamp, isFiscalTable, getProjectBizObjectId(), dboID);
        table.setDescription("isSysGen");
        //虚拟字段不创建dbo列
        for (IGspCommonField element : bizObject.getContainElements()) {
            if (!element.getIsVirtual()) {
                addColumnByBizElementWithChildElements((IGspCommonElement) ((element instanceof IGspCommonElement) ? element : null), table, bizObject.getIDElement().getID());

            }
        }
        return table;
    }

    /**
     * 根据业务实体字段新增列
     *
     * @param element
     * @param table
     */
    private void addColumnByBizElementWithChildElements(IGspCommonElement element, DatabaseObjectTable table, String primaryKeyID) {
        var childElementsCount = element.getChildElements().size();
        // ①不包含childElements
        if (childElementsCount == 0) {
            addColumn(element, table, primaryKeyID,false);
        } else if (childElementsCount == 1) {
            // ②包含1条childElement，列名使用当前字段标签，数据类型长度精度按照childElement
            var childEle = (IGspCommonElement) ((element.getChildElements().get(0) instanceof IGspCommonElement) ? element.getChildElements().get(0) : null);
            addColumn(element, table, primaryKeyID,false);
            childEle.setColumnID(element.getColumnID());
        } else {
            // ③包含多条childElements，列名使用childElement标签
            for (var GspCommonField : element.getChildElements()) {
                var childEle = (IGspCommonElement) GspCommonField;
                addColumn(childEle, table, primaryKeyID,false);
            }
        }
    }

    /**
     * @param element
     * @param table
     * @param primaryKeyID
     */
    private static void addColumn(IGspCommonElement element, DatabaseObjectTable table, String primaryKeyID,boolean usevc) {
        //20180801修改_由于支持找不到dbo时，以原dboID及名称重建dboTable，此情景下，该dboTable对应的列重建时，也使用原有dboColumnID;
        String refEleID = checkNull(element.getColumnID()) ? UUID.randomUUID().toString() : element.getColumnID();
        element.setColumnID(refEleID);

        boolean isPrimaryKey = primaryKeyID.equals(element.getID());
        RefObject<Integer> length = new RefObject<Integer>(0);
        RefObject<Integer> precision = new RefObject<Integer>(0);
        RefObject<Integer> scale = new RefObject<Integer>(0);
        getLengthPrecisionScale(element, length, precision, scale);
        //字段唯一则非空
        table.addColumn(refEleID, element.getLabelID(), element.getName(), getDataTypeByMDataType(element,usevc), length.argvalue, precision.argvalue, scale.argvalue, null, isPrimaryKey, isPrimaryKey, !isPrimaryKey, element.getIsMultiLanguage());
    }


    ///#endregion


    ///#region modify
    private void modifyDbo(GspBizEntityObject bizObject, String path, DatabaseObjectTable dbo, boolean isUsingTimeStamp) {
        // 20200506-BE添加dbo子节点，避免同步文件名
        // 对象编号修改，重命名设计时dbo文件
        //var newDboName = GetDboNameWithAppCode(bizObject.Code);
        //dtService.RenameDBOFile(path, newDboName, dbo.ID);
        DatabaseObjectTable table = modifyDboByBizObject(bizObject, dbo,false,false);
        // 对象名称修改后，重命名dbo的name属性
        //table.Name = bizObject.Name;
        // 20200623，导入dbo修改[启用时间戳]问题
        //table.IsUsingTimeStamp = this.GetIsUsingTimeStamp(bizObject, isUsingTimeStamp);
        dtService.saveDatabaseObjectTableWithoutFileName(path, table);
    }

    /**
     * 根据业务实体节点同步数据库对象（DBO）。
     * @param bizEntityObject  要同步DBO的业务实体节点
     * @param boId DBO所属的业务对象ID
     * @param usingTimeStamp 是否使用时间戳，使用时间戳的话，会更新DBO上的时间戳信息
     * @return 生成或者更新后的DBO对象
     */
    ///
    public  static  DatabaseObjectTable tryToGenOrModifyDbo(GspBizEntityObject bizEntityObject,String boId,boolean usingTimeStamp)
    {
        String dboId = bizEntityObject.getRefObjectName();
        DatabaseObjectTable databaseObjectTable = (DatabaseObjectTable) databaseObjectRtService.getDatabaseObject(dboId);
        boolean isDboNew = databaseObjectTable == null;
        if(isDboNew)
        {
            databaseObjectTable=new DatabaseObjectTable();
            String dboCode = SysnDboUtils. getDboNameWithAppCode(bizEntityObject.getCode(), boId);
            String dboName = bizEntityObject.getName();
            boolean isFiscalTable = false;
            boolean isUsingTimeStamp = SysnDboUtils.getIsUsingTimeStamp(bizEntityObject, usingTimeStamp);
            String dboID= bizEntityObject.getRefObjectName();
            if(dboID ==null||"".equals(dboID))
                dboID= UUID.randomUUID().toString();
            databaseObjectTable=   new DatabaseObjectTable(dboCode, dboName, false, false, isUsingTimeStamp, isFiscalTable, boId, dboID);
            bizEntityObject.setRefObjectName(databaseObjectTable.getId());
        }
        else
        {
            if(databaseObjectTable==null) {
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0031);
            }
        }
        modifyDboByBizObject4NoCode(bizEntityObject,databaseObjectTable,true,isDboNew);
        return databaseObjectTable;
    }


    /**
     *
     * 零代码生成dbo方法特定使用
     * 根据业务实体对象修改数据库表
     *
     * @param bizObject 业务实体对象
     * @param table     数据库表
     * @return 数据库表
     */
    private static DatabaseObjectTable modifyDboByBizObject4NoCode(GspBizEntityObject bizObject, DatabaseObjectTable table, boolean usevc,boolean isDboNew) {
        //修改列属性
        if (table == null) {
            //确认j版上对应的异常类
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0032, bizObject.getRefObjectName());
//            throw new BeManagerException(dboExceptionCode, String.format("不存在ID='%1$s'的数据库表。", bizObject.getRefObjectName()));
        }
        String primaryKey = bizObject.getColumnGenerateID().getElementID();
        //虚拟字段不创建dbo列
        for (IGspCommonField field : bizObject.getContainElements()) {

            var ele = (GspBizEntityElement) field;
            // 修改操作 不修改主键
            if (primaryKey.equals(field.getID()) && !isDboNew) {
                continue;
            }
            if (!ele.getIsVirtual()) {
                modifyColumnByBizElementWithChildElements(ele, table, bizObject.getIDElement().getID(),usevc);
            }
        }
        return table;
    }

    /**
     * 根据业务实体对象修改数据库表
     *
     * @param bizObject 业务实体对象
     * @param table     数据库表
     * @return 数据库表
     */
    public static DatabaseObjectTable modifyDboByBizObject(GspBizEntityObject bizObject, DatabaseObjectTable table, boolean usevc,boolean isDboNew) {
        //修改列属性
        if (table == null) {
            //确认j版上对应的异常类
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0032, bizObject.getRefObjectName());
//            throw new BeManagerException(dboExceptionCode, String.format("不存在ID='%1$s'的数据库表。", bizObject.getRefObjectName()));
        }
        String primaryKey = bizObject.getColumnGenerateID().getElementID();
        //虚拟字段不创建dbo列
        for (IGspCommonField field : bizObject.getContainElements()) {

            var ele = (GspBizEntityElement) field;
            // 修改操作 不修改主键
            if (primaryKey.equals(field.getID()) && !isDboNew) {
                continue;
            }
            //可能存在外部调用的情况，增加判断
            if(!isDboNew){
                //中储粮需求，修改dbo时，子表上的外键关联字段数据类型(ParentID)和dbo字段数据类型不一致，不再处理
                boolean isParentId = isParentId(bizObject, ele);
                if (isParentId)
                    continue;
            }
            if (!ele.getIsVirtual()) {
                modifyColumnByBizElementWithChildElements(ele, table, bizObject.getIDElement().getID(),usevc);
            }
        }
        return table;
    }
    /**
     * 判断当前节点上的字段是否是父级外键关联字段（ParentId）
     * @param bizObject
     * @param ele
     * @return
     */
    private static boolean isParentId(GspBizEntityObject bizObject, GspBizEntityElement ele) {
        GspAssociationKeyCollection keys = bizObject.getKeys();
        if (keys==null || keys.size()==0)
            return false;
        for (GspAssociationKey key : keys) {
            if (key.getSourceElement().equals(ele.getID()))
                return true;
        }
        return false;
    }

    /**
     * 根据业务实体字段修改数据库表列
     * 依照是否包含childElements，分情况讨论
     *
     * @param element      当前字段
     * @param table        数据库表
     * @param primaryKeyID 主键ID
     */
    private static void modifyColumnByBizElementWithChildElements(IGspCommonElement element, DatabaseObjectTable table, String primaryKeyID,boolean usevc) {

        var childElementsCount = element.getChildElements().size();
        // ①不包含childElements
        if (childElementsCount == 0) {
            modifyDboTableColumn(element, table, primaryKeyID,usevc);
        } else if (childElementsCount == 1) {
            // ②包含1条childElement，列编号及名称使用当前字段标签，全部按当前字段
            modifyDboTableColumn(element, table, primaryKeyID,usevc);
            ((IGspCommonElement) element.getChildElements().get(0)).setColumnID(element.getColumnID());
        } else {
            // ③包含多条childElements，列名使用childElement标签

            for (var GspCommonField : element.getChildElements()) {

                var childEle = (IGspCommonElement) GspCommonField;
                modifyDboTableColumn(childEle, table, primaryKeyID,usevc);
            }
        }
    }

    /**
     * 根据业务实体字段修改数据库表中的列
     *
     * @param ele          当前字段
     * @param table        数据库表
     * @param primaryKeyID 主键ID
     */
    private static void modifyDboTableColumn(IGspCommonElement ele, DatabaseObjectTable table, String primaryKeyID,boolean usevc) {
        if (!checkNull(((GspCommonElement) ele).getColumnID())) {
            DatabaseObjectColumn dboColumn = table.getColumnById(((GspCommonElement) ele).getColumnID());
            if (dboColumn != null) {
                //修改
                //  todo 中储粮需求，修改dbo时，关联字段数据类型是Varchar类型、dbo上字段数据类型是LongInt类型，临时不做重新修改的处理，后续根据实际关联的类型处理
                if(ele.getObjectType()==GspElementObjectType.Association && dboColumn.getDataType()==DataType.LongInt)
                    return;
                modifyColumn((GspCommonElement) ele, table, primaryKeyID,usevc);
            } else {
                //确认j版上对应的异常类
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0033, ele.getColumnID());
//                throw new BeManagerException(dboExceptionCode, String.format("dbo上不存在ID='%1$s'列。", ((GspCommonElement)ele).ColumnID));
            }
        } else {
            //创建
            //创建前，判断是否已存在同名的dbo列:
            //① 存在同名dbo列，则修改该列;
            //② 不存在，新建列；
            DatabaseObjectColumn dboColumn = table.getColumnByCode(ele.getLabelID());
            if (dboColumn != null) {
                // 20190112修改-bug274325，新增字段，与dbo中有重复标签的列，则抛异常；大小写不一致，也认为一样。
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0034, ele.getLabelID(), ele.getLabelID());
                //((GspCommonElement)ele).ColumnID = dboColumn.ID;
                //modifyColumn((GspCommonElement)ele, table, primaryKeyID);
            } else {
                addColumn((GspCommonElement) ele, table, primaryKeyID,usevc);
            }
        }
    }

    private static void modifyColumn(IGspCommonElement element, DatabaseObjectTable table, String primaryKeyID,boolean usevc) {
        if (checkNull(element.getColumnID())) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0035, element.getName());
        }
        boolean isPrimaryKey = primaryKeyID.equals(element.getID());
        RefObject<Integer> length = new RefObject<Integer>(0);
        RefObject<Integer> precision = new RefObject<Integer>(0);
        RefObject<Integer> scale = new RefObject<Integer>(0);
        getLengthPrecisionScale(element, length, precision, scale);

        DatabaseObjectColumn column = table.getColumnById(element.getColumnID());

        DataType dataType = getDataTypeByMDataType(element,usevc);
        boolean isUnique = column.isUnique();
        boolean isI18N = element.getIsMultiLanguage();
        //修复Bug 348603: dbo改成NVarchar之后，BE保存并同步会重新覆盖数据类型为VarChar
        switch (dataType) {
            case Varchar:
                if (column.getDataType() == DataType.NVarchar) {
                    dataType = DataType.NVarchar;
                }
                break;
            case Clob:
                if (column.getDataType() == DataType.NClob) {
                    dataType = DataType.NClob;
                }
                break;
            case Char:
                // 20200623:修复问题导入Boolean类型dbo列会被修改为Char问题
                if (column.getDataType() == DataType.Boolean) {
                    dataType = DataType.Boolean;
                    length.argvalue = column.getLength();
                    precision.argvalue = column.getPrecision();
                    scale.argvalue = column.getScale();
                }
                break;
            case Int:
                if(element.getMDataType()==GspElementDataType.Integer &&column.getDataType()==DataType.SmallInt){
                    dataType=DataType.SmallInt;
                }
                break;
        }



        var currentColumnDefaultValue = column.getDefaultValue();

        var columnLength = (length.argvalue > column.getLength()) ? length.argvalue : column.getLength();
        if (element.getMDataType() == GspElementDataType.Boolean) {
            columnLength = 1;
        }

        if(element.getMDataType()==GspElementDataType.Date&&column.getDataType()== DataType.Varchar&&column.getLength()==8)
        {
            dataType=DataType.Varchar;
            columnLength=8;
        }
        //字段唯一则非空
        table.modifyColumn(element.getColumnID(), element.getName(), dataType, columnLength, precision.argvalue, scale.argvalue, currentColumnDefaultValue, isUnique, isPrimaryKey,column.isNullable(), isI18N);
    }


    ///#endregion


    ///#region util

    /**
     * dbo重名校验，校验dbo文件名不重复
     *
     * @param dboName 对象编号
     * @param
     * @return
     */
    private void checkDboFileNameRepeat(String path, String dboName) {
        if (dtService.isDatabaseObjectFileExist(path, dboName)) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0036, dboName);
        }
    }

    /**
     * dbo重名校验，表名不重复
     *
     * @param dboName 对象编号
     * @return
     */
    private void checkDboTableNameRepeat(String path, String dboName, String dboID) {
        boolean tempVar = dtService.isExistDatabaseObject(path, dboName, dboID);
        if (tempVar) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0037, dboName);
        }
    }

    //20190627修改_修改dbo文件名逻辑直接调用dbo服务
    ///// <summary>
    ///// 设计时dbo文件已存在时，若修改对象编号，相应dbo文件重命名
    ///// 但[Name]属性不修改(即表名不修改)，[ShowName]属性不修改
    ///// </summary>
    ///// <param name="dboID">数据库对象ID</param>
    ///// <param name="newDboFileName">新dbo文件名</param>
    ///// <param name="path"></param>
    //private void RenameDboFileName(string dboID, string newDboFileName, string path)
    //{
    //	// 若对象编号修改，则dbo的文件名跟着修改，但[Name]属性不修改(即表名不修改)，[ShowName]属性不修改
    //	// 根据dbo名判断对象是否改名，若对象编号已修改，则重命名dbo文件
    //	var dboInfo = new DatabaseObjectInfo();
    //	dtService.IsExistDatabaseObject(path, null, dboID, out dboInfo);
    //	var oldDboName = System.IO.Path.GetFileNameWithoutExtension(dboInfo.FilePath);
    //	if (newDboFileName != oldDboName)
    //	{
    //		// dbo文件重名校验通过，重命名dbo文件
    //		checkDboFileNameRepeat(path, newDboFileName);
    //		dtService.RenameDBOFile(path, newDboFileName, dboID);
    //	}
    //}

    /**
     * 解决lcm的长度精度小数位数与beElementDataType中长度精度小数位数中表达不一致问题
     *
     * @param element   业务实体字段
     * @param length    column中长度
     * @param precision column中精度
     * @param scale     column中小数位数
     */
    private static void getLengthPrecisionScale(IGspCommonElement element, RefObject<Integer> length, RefObject<Integer> precision, RefObject<Integer> scale) {
        length.argvalue = 0;
        precision.argvalue = 0;
        scale.argvalue = 0;

        // 解决lcm的长度精度小数位数与beElementDataType中长度精度小数位数中表达不一致问题
        switch (element.getMDataType()) {
            //整型，赋值长度
            case Integer:
                length.argvalue = 0;
                precision.argvalue = 0;
                scale.argvalue = 0;
                break;
            //字符串，赋值长度
            case String:
                length.argvalue = element.getLength();
                precision.argvalue = 0;
                scale.argvalue = 0;
                break;
            //浮点数字，赋值精度，小数位数
            case Decimal:
                length.argvalue = 0;
                precision.argvalue = element.getLength();
                scale.argvalue = element.getPrecision();
                break;
            //布尔型
            case Boolean:
                length.argvalue = 1;
                precision.argvalue = 0;
                scale.argvalue = 0;
                break;
            //其他，0,0,0
        }
    }

    /**
     * 字段类型转换
     *
     * @param ele 业务实体字段类型
     * @return 数据库对象字段类型
     */
    private static DataType getDataTypeByMDataType(IGspCommonElement ele,boolean usevc) {
        GspElementDataType mDataType = ele.getMDataType();
        //多语字段的控制
        if (ele.getIsMultiLanguage() && !usevc) {
            switch (mDataType) {
                case String:
                    return DataType.NVarchar;
                case Text:
                    return DataType.NClob;
                default:
                    throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0038,  ele.getName());
            }
        }


        //字段数据类型转换为列数据类型
        switch (mDataType) {
            case String:
                //如果字段类型为枚举，关联，父ID，则做另外处理
                if(!usevc || isUseVarchar(ele)){
                    return DataType.Varchar;
                }
                return DataType.NVarchar;
            case Integer:
                return DataType.Int;
            case Decimal:
                return DataType.Decimal;
            case Boolean:
                return DataType.Char;
            case Text:
                return DataType.Clob;
            case Date:
                return DataType.DateTime;
            case DateTime:
                return DataType.TimeStamp;
            case Binary:
                return DataType.Blob;
            default:
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0039, mDataType.toString());
        }
    }

    //判断是否需要用到varchar类型的数据
    private static Boolean isUseVarchar(IGspCommonElement element){
        if(element.getBelongObject() == null){
            return true;
        }
        if (element.getBelongObject().getIDElement() == element){
            return true;
        }
        if (element.getBelongObject().getKeys()!=null && element.getBelongObject().getKeys().size()>0){
            if (element.getBelongObject().getKeys().get(0).getSourceElement().equals(element.getID())){
                return true;
            }
        }
        if(element.getIsUdt()){
            return true;
        }
        return !element.getObjectType().equals(GspElementObjectType.None);
    }



    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

    private String getAppCode() {
        return this.metadataService.getGspProjectInfo(projectPath).getAppCode();
    }

    private String getProjectBizObjectId() {
        return this.metadataService.getGspProjectInfo(projectPath).getBizobjectID();
    }

    /**
     * dbo编号添加[关键应用]前缀
     *
     * @param objCode
     * @return
     */
    private String GetDboNameWithAppCode(String objCode) {
        String appCode = getAppCode();
        return String.format("%1$s%2$s", appCode, objCode);
    }

}
